﻿using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.DynamicForm.Operation;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs;
using Kingdee.BOS.Core.Metadata.ConvertElement;
using Kingdee.BOS.Core.Permission;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Kingdee.BOS.Util;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.SqlBuilder;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.JSON;
using DzInfo.Model.FanWei;
using Kingdee.BOS.Core.Interaction;
using Kingdee.BOS.Orm.Metadata.DataEntity;
using Kingdee.BOS.Core.Bill;
using Kingdee.BOS.Core.Metadata.FormElement;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.DynamicForm.PlugIn;

namespace DzInfo.Tools
{
    public static class KingdeeTools
    {
        /// <summary>
        /// 将操作结果加到操作集合
        /// </summary>
        /// <param name="orc"></param>
        /// <param name="result"></param>
        public static void WriteOperateResultCollection(OperateResultCollection orc, IOperationResult result)
        {
            foreach (var item in result.OperateResult)
            {
                orc.Add(item);
            }
            if (result.ValidationErrors.Count > 0)
            {
                foreach (var err in result.ValidationErrors)
                {
                    orc.Add(new OperateResult() { Message = err.Message, MessageType = MessageType.FatalError, SuccessStatus = false });
                }
            }
            if (!result.IsSuccess && result.InteractionContext != null && !result.InteractionContext.SimpleMessage.IsNullOrEmptyOrWhiteSpace())
            {
                orc.Add(new OperateResult() { Message = result.InteractionContext.SimpleMessage, MessageType = MessageType.FatalError, SuccessStatus = false });
            }
        }
        /// <summary>
        /// 下推服务-默认转换规则
        /// </summary>
        /// <param name="ctx">上下文</param>
        /// <param name="sourceFormID">源单formId</param>
        /// <param name="targetFormID">目标单formId</param>
        /// <param name="entryEntityKey">单据体标识</param>
        /// <param name="billTypeID">源单单据类型</param>
        /// <param name="targetBillTypeId">目标单据类型</param>
        /// <param name="primaryKeyValue">源单FID</param>
        /// <param name="entryPrimaryKeyValue">源单分录</param>
        /// <param name="ruleStr">指定转换规则</param>
        /// <returns></returns>
        public static ConvertOperationResult DzConvertService(Context ctx, string sourceFormID, string targetFormID, string entryEntityKey, string billTypeID, string targetBillTypeId, string primaryKeyValue, string entryPrimaryKeyValue)
        {
            List<ConvertRuleElement> convertRules = ConvertServiceHelper.GetConvertRules(ctx, sourceFormID, targetFormID);
            var convertRule = convertRules.FirstOrDefault();
            List<ListSelectedRow> list2 = new List<ListSelectedRow>();
            Dictionary<string, string> fieldValues = new Dictionary<string, string>();
            fieldValues.Add(entryEntityKey, entryPrimaryKeyValue);
            list2.Add(new ListSelectedRow(primaryKeyValue, entryPrimaryKeyValue, 0, sourceFormID)
            {
                EntryEntityKey = entryEntityKey,
                FieldValues = fieldValues,
                BillTypeID = billTypeID
            });
            PushArgs serviceArgs = new PushArgs(convertRule, list2.ToArray())
            {
                TargetBillTypeId = targetBillTypeId
            };
            OperateOption operateOption = OperateOption.Create();
            ConvertOperationResult operationResult = ConvertServiceHelper.Push(ctx, serviceArgs, operateOption);
            return operationResult;
        }
        /// <summary>
        /// 下推服务-指定转换规则
        /// </summary>
        /// <param name="ctx">上下文</param>
        /// <param name="sourceFormID">源单formId</param>
        /// <param name="targetFormID">目标单formId</param>
        /// <param name="entryEntityKey">单据体标识</param>
        /// <param name="billTypeID">源单单据类型</param>
        /// <param name="targetBillTypeId">目标单据类型</param>
        /// <param name="primaryKeyValue">源单FID</param>
        /// <param name="entryPrimaryKeyValue">源单分录</param>
        /// <param name="ruleStr">指定转换规则</param>
        /// <returns></returns>
        public static ConvertOperationResult DzConvertService(Context ctx, string sourceFormID, string targetFormID, string entryEntityKey, string billTypeID, string targetBillTypeId, string primaryKeyValue, string entryPrimaryKeyValue, string ruleStr)
        {
            List<ConvertRuleElement> convertRules = ConvertServiceHelper.GetConvertRules(ctx, sourceFormID, targetFormID);
            var convertRule = convertRules.Find(f => f.Id.Equals(ruleStr));
            List<ListSelectedRow> list2 = new List<ListSelectedRow>();
            Dictionary<string, string> fieldValues = new Dictionary<string, string>();
            fieldValues.Add(entryEntityKey, entryPrimaryKeyValue);
            list2.Add(new ListSelectedRow(primaryKeyValue, entryPrimaryKeyValue, 0, sourceFormID)
            {
                EntryEntityKey = entryEntityKey,
                FieldValues = fieldValues,
                BillTypeID = billTypeID
            });
            PushArgs serviceArgs = new PushArgs(convertRule, list2.ToArray())
            {
                TargetBillTypeId = targetBillTypeId
            };
            OperateOption operateOption = OperateOption.Create();
            ConvertOperationResult operationResult = ConvertServiceHelper.Push(ctx, serviceArgs, operateOption);
            return operationResult;
        }
        /// <summary>
        /// 获取过滤方案
        /// </summary>
        /// <param name="ctx">上下文</param>
        /// <param name="formId">单据或账表的标识</param>
        /// <returns></returns>
        public static DynamicObjectCollection GetSchemes(Context ctx, string formId)
        {
            string sql = string.Format(@"/*dialect*/ 
            select FSCHEMENAME from T_BAS_FILTERSCHEME where FFORMID='{0}'  AND FUSERID>0 ", formId);
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(ctx, sql);
            return doc;
        }
        /// <summary>
        /// 保存自定日志表
        /// </summary>
        /// <param name="context"></param>
        /// <param name="log"></param>
        /// <param name="isAsy">是否异步保存，默认异步</param>
        public static void SaveLog(Context context, SyncLog log, string tableName, bool isAsy = true)
        {
            List<SqlParam> sqlParams = new List<SqlParam>();
            string sql = "";
            log.GetInsertSqlAndParams(out sqlParams, out sql, tableName);
            if (isAsy)
            {
                using (var trans = new KDTransactionScope(TransactionScopeOption.Suppress))
                {
                    int i = DBUtils.Execute(context, sql, sqlParams);
                    if (i > 0)
                    {
                        return;
                    }
                }
            }
            else
            {
                int i = DBUtils.Execute(context, sql, sqlParams);
                if (i > 0)
                {
                    return;
                }
            }
        }
        /// <summary>
        /// 判断字符串是否在枚举中
        /// </summary>
        /// <param name="formId"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsStringInEnum(string formId, Type type)
        {
            try
            {
                // 尝试将字符串转换为枚举
                Enum.Parse(type, formId);
                // 如果没有抛出异常，说明字符串在枚举中
                return true;
            }
            catch (ArgumentException)
            {
                // 如果抛出ArgumentException，说明字符串不在枚举中
                return false;
            }
        }
        /// <summary>
        /// 获取单据或者基础资料
        /// </summary>
        /// <param name="formId">界面标识</param>
        /// <param name="fid">单据ID</param>
        /// <returns></returns>
        public static DynamicObject GetDynamicObjectByFormIdAndId(Context context, string formId, object fid)
        {
            DynamicObject obj = null;
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, formId);
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = formId;
            queryParam.FilterClauseWihtKey = string.Format(" {0}='{1}'", meta.BusinessInfo.GetForm().PkFieldName, fid);
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            if (objs.Length > 0) obj = objs.FirstOrDefault();
            return obj;
        }
        /// <summary>
		/// 获取单据或者基础资料
		/// </summary>
		/// <param name="formId">界面标识</param>
		/// <param name="number">编码</param>
		/// <returns></returns>
		public static DynamicObject GetDynamicObjectByFormIdAndNumber(Context context, string formId, object number)
        {
            DynamicObject obj = null;
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, formId);
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = formId;
            queryParam.FilterClauseWihtKey = string.Format(" {0}='{1}'", meta.BusinessInfo.GetForm().NumberFieldKey, number);
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            if (objs.Length > 0) obj = objs.FirstOrDefault();
            return obj;
        }
        /// <summary>
        /// 通过用户ID获取用户对应的员工姓名
        /// </summary>
        /// <param name="context"></param>
        /// <param name="creatorId"></param>
        /// <returns></returns>
        public static string GetCreator(Context context, int creatorId)
        {
            string empNumber = "";
            if (creatorId > 0)
            {
                var emp = GetDynamicObjectByFormIdAndId(context, "SEC_User", creatorId);
                if (emp != null)
                {
                    DynamicObject obj = emp["FLinkObject"] as DynamicObject;
                    if (obj != null)
                    {
                        empNumber = obj["number"].ToString();
                    }
                }
            }
            if (!empNumber.IsNullOrEmptyOrWhiteSpace())
            {
                var empinfo = GetDynamicObjectByFormIdAndNumber(context, "BD_Empinfo", empNumber);
                //string dep1 = empinfo["F_PXIA_Text1"] == null ? "" : empinfo["F_PXIA_Text1"].ToString();
                //string dep2 = empinfo["F_PXIA_Text14"] == null ? "" : empinfo["F_PXIA_Text14"].ToString();
                string name = empinfo["name"] == null ? "" : empinfo["name"].ToString();
                return name;
            }
            return "超级管理员";
        }
        /// <summary>
        /// 根据单据获取单据附件
        /// </summary>
        /// <param name="context"></param>
        /// <param name="formId"></param>
        /// <param name="billId"></param>
        /// <returns></returns>
        public static DynamicObject[] GetAttachments(Context context, string formId, object billId)
        {
            string filterStr = string.Format("FBillType = '{0}' and FInterId IN ('{1}')", formId, billId);
            OQLFilter filter = OQLFilter.CreateHeadEntityFilter(filterStr);
            DynamicObject[] attaDynObjs = BusinessDataServiceHelper.Load(context, FormIdConst.BOS_Attachment, null, filter);
            return attaDynObjs;
        }
        /// <summary>
        /// 打开外部链接
        /// </summary>
        /// <param name="view"></param>
        /// <param name="requestid"></param>
        /// <param name="context"></param>
        /// <param name="formid"></param>
        /// <param name="workcode"></param>
        public static void openUrl(IDynamicFormView view, int requestid, Context context, string formid, string workcode)
        {
            //workcode = "ZJRM0313";
            //获取同步设置和URL
            DynamicObject setting = GetKToOSysSynSetting(context, formid, 0);
            string appkey = Convert.ToString(setting["FOSysURL2"]);
            string esbUrl = Convert.ToString(setting["FLct"]);
            string oaUrl = Convert.ToString(setting["FOAURL"]);
            string soTokenUrl = Convert.ToString(setting["FssoToken"]);
            //string appid = Convert.ToString(setting["Fappid"]);
            //soTokenUrl = soTokenUrl + $"?appid={appid}&loginid={workcode}";
            esbUrl = esbUrl + $"?requestid={requestid}";
            //获取OA流程图Url
            FlowChart result = InvokeHelper.Post(esbUrl, appkey, workcode);
            var chartUrl = result.data.chartUrl;
            //获取ssoToken  FssoToken
            var ssoTokenResult = InvokeHelper.Post(soTokenUrl);
            //拼接流程图url
            oaUrl = oaUrl + chartUrl + $"&ssoToken={ssoTokenResult}";
            //string url = @"http://www.baidu.com";
            // 方式一
            // 直接打开浏览器并跳转到此Url地址
            //ViewCommonAction.ShowWebURL(view, url);
            //view.SendDynamicFormAction(view);

            // 方式二
            // 弹窗打开Url地址
            JSONObject webobj = new JSONObject();
            webobj["source"] = oaUrl;
            webobj["height"] = 600;
            webobj["width"] = 910;

            //默认打开全屏显示
            webobj["isfullscreen"] = true;

            ////是否新弹出一个浏览器窗口（or选项卡）打开网页地址
            webobj["isweb"] = true;

            webobj["title"] = "OA流程图";

            view.AddAction("ShowKDWebbrowseForm", webobj);
            view.SendAynDynamicFormAction(view);
        }
        /// <summary>
        /// 获取同步设置，获取组织所有设置，如果存在多行就增加表单Id去找到指定业务对象同步设置
        /// </summary>
        /// <param name="context"></param>
        /// <param name="formId"></param>
        /// <param name="orgId"></param>
        /// <returns></returns>
        public static DynamicObject GetKToOSysSynSetting(Context context, string formId, long orgId)
        {
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, "qqq_KAndOSysSynSet");
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = "qqq_KAndOSysSynSet";
            //queryParam.FilterClauseWihtKey = string.Format(" FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' and FUSEORGID={0}", orgId);
            queryParam.FilterClauseWihtKey = string.Format(" FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' ");
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            if (objs.Length > 1)
            {
                var findRows = objs.Where(w => (w["FormId"] as DynamicObject) != null && Convert.ToString((w["FormId"] as DynamicObject)["id"]).EqualsIgnoreCase(formId));
                if (findRows != null && findRows.Count() > 0)
                {
                    return findRows.First();
                }
            }
            else if (objs.Length == 1)
            {
                return objs.First();

            }
            return null;
        }
        /// <summary>
        /// 判断操作结果是否成功，如果不成功，则直接抛错中断进程
        /// </summary>
        /// <param name="BusinessInfoOperationResult">服务插件的操作结果</param>
        /// <param name="opResult">当前操作结果</param>
        /// <returns></returns>
        public static bool CheckOpResult(IOperationResult BusinessInfoOperationResult, IOperationResult opResult)
        {
            bool isSuccess = false;
            if (opResult.IsSuccess == true)
            {
                // 操作成功
                isSuccess = true;
            }
            else
            {
                if (opResult.InteractionContext != null
                && opResult.InteractionContext.Option.GetInteractionFlag().Count > 0)
                {// 有交互性提示

                    // 传出交互提示完整信息对象
                    BusinessInfoOperationResult.InteractionContext = opResult.InteractionContext;
                    // 传出本次交互的标识，
                    // 用户在确认继续后，会重新进入操作；
                    // 将以此标识取本交互是否已经确认过，避免重复交互
                    BusinessInfoOperationResult.Sponsor = opResult.Sponsor;

                    // 抛出错误，终止本次操作
                    throw new KDBusinessException("", "本次操作需要用户确认是否继续，暂时中断。" + opResult.InteractionContext.SimpleMessage);
                }
                else
                {
                    // 操作失败，拼接失败原因，然后抛出中断
                    opResult.MergeValidateErrors();
                    if (opResult.OperateResult == null)
                    {// 未知原因导致提交失败
                        throw new KDBusinessException("", "未知原因导致自动提交、审核失败！");
                    }
                    else
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.AppendLine("自动提交、审核失败，失败原因：");
                        foreach (var operateResult in opResult.OperateResult)
                        {
                            sb.AppendLine(operateResult.Message);
                        }
                        throw new KDBusinessException("", sb.ToString());
                    }
                }
            }
            return isSuccess;
        }
        /// <summary>
        /// 将操作结果转换成字符串
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public static string GetOperateResultStr(IOperationResult result)
        {
            List<string> infos = new List<string>();
            if (result.OperateResult != null && result.OperateResult.Count() > 0)
            {
                foreach (var item in result.OperateResult)
                {
                    infos.Add(item.Message);
                }
            }
            if (result.ValidationErrors.Count > 0)
            {
                foreach (var err in result.ValidationErrors)
                {
                    infos.Add(err.Message);
                }
            }
            if (!result.IsSuccess && result.InteractionContext != null && !result.InteractionContext.SimpleMessage.IsNullOrEmptyOrWhiteSpace())
            {
                infos.Add(result.InteractionContext.SimpleMessage);
            }
            return string.Join(";", infos);
        }
        /// <summary>
        /// 判断数据对象是否包含实体属性
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool IsContainsKey(DynamicObject obj, string key)
        {
            bool b = false;
            DynamicPropertyCollection p = obj.DynamicObjectType.Properties;
            if (p != null && p.Count > 0)
            {
                var findRows = p.ToArray().Where(w => w.Name.EqualsIgnoreCase(key));
                if (findRows != null && findRows.Count() > 0)
                {
                    b = true;
                }
            }
            return b;
        }
        /// <summary>
        /// 创建单据视图
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="formId">单据标识ID</param>
        /// <returns></returns>
        public static IBillView CreateBillView(Context context, string formId)
        {
            // 读取物料的元数据
            FormMetadata meta = MetaDataServiceHelper.Load(context, formId) as FormMetadata;
            Form form = meta.BusinessInfo.GetForm();
            // 创建用于引入数据的单据view
            Type type = Type.GetType("Kingdee.BOS.Web.Import.ImportBillView,Kingdee.BOS.Web");
            var billView = (IDynamicFormViewService)Activator.CreateInstance(type);
            // 开始初始化billView：
            // 创建视图加载参数对象，指定各种参数，如FormId, 视图(LayoutId)等
            BillOpenParameter openParam = CreateOpenParameter(context, meta);
            // 动态领域模型服务提供类，通过此类，构建MVC实例
            var provider = form.GetFormServiceProvider();
            billView.Initialize(openParam, provider);
            return billView as IBillView;
        }
        private static BillOpenParameter CreateOpenParameter(Context context, FormMetadata meta)
        {
            Form form = meta.BusinessInfo.GetForm();
            // 指定FormId, LayoutId
            BillOpenParameter openParam = new BillOpenParameter(form.Id, meta.GetLayoutInfo().Id);
            // 数据库上下文
            openParam.Context = context;
            // 本单据模型使用的MVC框架
            openParam.ServiceName = form.FormServiceName;
            // 随机产生一个不重复的PageId，作为视图的标识
            openParam.PageId = Guid.NewGuid().ToString();
            // 元数据
            openParam.FormMetaData = meta;
            // 界面状态：新增 (修改、查看)
            openParam.Status = OperationStatus.ADDNEW;
            // 单据主键：本案例演示新建物料，不需要设置主键
            openParam.PkValue = null;
            // 界面创建目的：普通无特殊目的 （为工作流、为下推、为复制等）
            openParam.CreateFrom = CreateFrom.Default;
            // 基础资料分组维度：基础资料允许添加多个分组字段，每个分组字段会有一个分组维度
            // 具体分组维度Id，请参阅 form.FormGroups 属性
            openParam.GroupId = "";
            // 基础资料分组：如果需要为新建的基础资料指定所在分组，请设置此属性
            openParam.ParentId = 0;
            // 单据类型
            openParam.DefaultBillTypeId = "";
            // 业务流程
            openParam.DefaultBusinessFlowId = "";
            // 主业务组织改变时，不用弹出提示界面
            openParam.SetCustomParameter("ShowConfirmDialogWhenChangeOrg", false);
            // 插件
            List<AbstractDynamicFormPlugIn> plugs = form.CreateFormPlugIns();
            openParam.SetCustomParameter(FormConst.PlugIns, plugs);
            PreOpenFormEventArgs args = new PreOpenFormEventArgs(context, openParam);
            foreach (var plug in plugs)
            {// 触发插件PreOpenForm事件，供插件确认是否允许打开界面
                plug.PreOpenForm(args);
            }
            if (args.Cancel == true)
            {// 插件不允许打开界面
                // 本案例不理会插件的诉求，继续....
            }
            // 返回
            return openParam;
        }
        /// <summary>
        /// 源单行内码，多行下推
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="sourceFormID"></param>
        /// <param name="targetFormID"></param>
        /// <param name="entryEntityKey"></param>
        /// <param name="billTypeID"></param>
        /// <param name="targetBillTypeId"></param>
        /// <param name="primaryKeyValue"></param>
        /// <param name="entryPrimaryKeyValues"></param>
        /// <param name="ruleStr"></param>
        /// <returns></returns>
        public static ConvertOperationResult DzConvertServiceList(Context ctx, string sourceFormID, string targetFormID, string entryEntityKey, string billTypeID, string targetBillTypeId, string primaryKeyValue, List<string> entryPrimaryKeyValues, string ruleStr)
        {
            List<ConvertRuleElement> convertRules = ConvertServiceHelper.GetConvertRules(ctx, sourceFormID, targetFormID);
            var convertRule = convertRules.Find(f => f.Id.Equals(ruleStr));
            List<ListSelectedRow> list2 = new List<ListSelectedRow>();
            foreach(var eid in entryPrimaryKeyValues)
            {
                Dictionary<string, string> fieldValues = new Dictionary<string, string>();
                fieldValues.Add(entryEntityKey, eid);
                list2.Add(new ListSelectedRow(primaryKeyValue, eid, 0, sourceFormID)
                {
                    EntryEntityKey = entryEntityKey,
                    FieldValues = fieldValues,
                    BillTypeID = billTypeID
                });
            }
            PushArgs serviceArgs = new PushArgs(convertRule, list2.ToArray())
            {
                TargetBillTypeId = targetBillTypeId
            };
            OperateOption operateOption = OperateOption.Create();
            ConvertOperationResult operationResult = ConvertServiceHelper.Push(ctx, serviceArgs, operateOption);
            return operationResult;
        }
    }
}
